package com.hoopchina.service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;

/**
 * Networking client which provides services for all modules in application
 * @author Si Wei
 *
 */
public class Networking {
	public static int                ConnectTimeout = 5000;
	public static int                ReadTimeout    = 1000;
	/**
	 * Get String from the specified web URL synchronously
	 * @throws Exception 
	 */
	public static String downloadString(final String url) throws Exception {
		//AndroidHttpClient
		// DefaultHttpClient
		DefaultHttpClient httpclient = new DefaultHttpClient();
		// HttpGet
		HttpGet httpget = new HttpGet(url);
		// ResponseHandler
		ResponseHandler<String> responseHandler = new BasicResponseHandler();

		String outputString = "";
		try {
			outputString = httpclient.execute(httpget, responseHandler);
		} catch ( Exception e ) {
			throw e;
		}
		httpclient.getConnectionManager().shutdown();

		return outputString;
	}

	/**
	 * Post String from the specified web URL synchronously
	 * @throws Exception 
	 */
	public static String uploadString(final String url,
			final Map<String, String> params) throws Exception {
		
		String result = "";
		
		try {
			// DefaultHttpClient
			DefaultHttpClient httpClient = new DefaultHttpClient();

			// HttpPost
			HttpPost httpPost = new HttpPost(url);
			ArrayList<BasicNameValuePair> postData = new ArrayList<BasicNameValuePair>();
			for (Map.Entry<String, String> m : params.entrySet()) {
				postData.add(new BasicNameValuePair(m.getKey(), m.getValue()));
			}
			UrlEncodedFormEntity entity = new UrlEncodedFormEntity(postData,
					HTTP.UTF_8);
			httpPost.setEntity(entity);

			HttpResponse response = httpClient.execute(httpPost);
			@SuppressWarnings("unused")
			int statusCode = MappingHttpStatus( response.getStatusLine().getStatusCode() );

			HttpEntity httpEntity = response.getEntity();
			result += convertStreamToString(httpEntity.getContent());
			
			httpClient.getConnectionManager().shutdown();

		} catch (Exception e) {
			throw e;
		}
		return result;
	}

	/**
	 * After get String from the specified web URL, send message to handler asynchronously
	 */
	public static void downloadStringAsync(final String url, final Handler handler){
		new Thread() {
			public void run() {
				String outputString = "";
				try {
					outputString = downloadString(url);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

				Message msg = handler.obtainMessage();
				msg.obj = outputString;
				handler.sendMessage(msg);
			}

		}.start();
	}

	/**
	 * Post String from the specified web URL asynchronously
	 */
	public static void uploadStringAsync(final String url,
			final Map<String, String> params, final Handler handler) {
		new Thread() {
			public void run() {
				String outputString = "";
				try {
					outputString = uploadString(url, params);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

				Message msg = handler.obtainMessage();
				msg.obj = outputString;
				handler.sendMessage(msg);
			}

		}.start();
	}

	/**
	 * convert input stream to string
	 */
	private static String convertStreamToString(InputStream is) {
		BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		StringBuilder sb = new StringBuilder();

		String line = null;
		try {
			while ((line = reader.readLine()) != null) {
				sb.append(line + "\n");
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return sb.toString();
	}
	
	/**
	 * Get bitmap with given url, returned value should be checked if it's null
	 * @param aUrl url string
	 * @return bitmap image
	 */
	public static Bitmap getBitmapFromUrl( String aUrl ) {
		Bitmap bitmap = null;
		try {
			URL url = new URL( aUrl );
			HttpURLConnection conn  = (HttpURLConnection)url.openConnection();
			conn.setDoInput(true);
			conn.setConnectTimeout( ConnectTimeout );
			conn.setReadTimeout( ReadTimeout );
			conn.connect(); 
			InputStream inputStream=conn.getInputStream();
			bitmap = BitmapFactory.decodeStream(inputStream);
		}
	    catch ( MalformedURLException urlEx ) { 
	    	urlEx.printStackTrace();
	    } 
	    catch ( IOException ioEx ) {
	    	ioEx.printStackTrace();
	    }
	    return bitmap;
	}
	
    /*
     * 返回相应url的输入流
     * 
     */
	public static InputStream getStreamFromUrl( String aUrl ) 
	throws MalformedURLException, IOException {
		URL url = new URL( aUrl );
		URLConnection conn = url.openConnection();
		conn.setConnectTimeout( ConnectTimeout );
		conn.setReadTimeout( ReadTimeout );
		return conn.getInputStream();
	}
	
	public static HttpResponse getResponseFromUrl( String aUrl ) 
	throws ClientProtocolException, IOException {
		HttpResponse response = null;
		HttpClient client = new DefaultHttpClient();
        HttpGet get = new HttpGet( aUrl );
        response = client.execute( get );
        return response;
	}
	
	/**
	 * Mapping android HttpStatus to our custom HttpStatusCode
	 * @param aHttpStatusCode
	 * @return
	 */
	private static int MappingHttpStatus( int aHttpStatusCode ) {
		int retCode = -1;
		switch ( aHttpStatusCode ) {
		case HttpStatus.SC_OK:
		case HttpStatus.SC_ACCEPTED:
			retCode = HttpStatusCode.OK;
			break;
		case HttpStatus.SC_NOT_FOUND:
		case HttpStatus.SC_BAD_GATEWAY:
		case HttpStatus.SC_BAD_REQUEST:
			retCode = HttpStatusCode.NOK;
			break;
		default:
			break;
		}
		return retCode;
	}
}
